{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**问题：**\n",
    "假设你正在为一个电影推荐系统设计一个简单的KNN算法。我们有以下一些用户的电影评分数据，数据由两个特征组成：用户对电影A和电影B的评分，分别在1-5之间。用户的标签（电影类型偏好）是动作片（标签0）或者是喜剧片（标签1）。我们有一个新用户，他给电影A评分为3，电影B评分为4。请问这个用户可能偏好哪种类型的电影？\n",
    "\n",
    "**数据：**\n",
    "\n",
    "| 用户   | 电影A评分 | 电影B评分 | 偏好类型 |\n",
    "| ------ | --------- | --------- | -------- |\n",
    "| 用户1  | 5         | 1         | 动作片   |\n",
    "| 用户2  | 4         | 2         | 动作片   |\n",
    "| 用户3  | 2         | 5         | 喜剧片   |\n",
    "| 用户4  | 1         | 4         | 喜剧片   |\n",
    "| 用户5  | 3         | 2         | 动作片   |\n",
    "| 用户6  | 2         | 5         | 喜剧片   |\n",
    "\n",
    "你需要做以下步骤：\n",
    "1. 构造数据\n",
    "2. 创建KNN模型\n",
    "3. 使用数据训练模型\n",
    "4. 预测新用户的喜好"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 0. 引入核心包"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.neighbors import KNeighborsClassifier"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. X, y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "X = np.array([\n",
    "    [5, 1],\n",
    "    [4, 2],\n",
    "    [2, 5],\n",
    "    [1, 4],\n",
    "    [3, 2],\n",
    "    [2, 5]\n",
    "])\n",
    "\n",
    "y = np.array([0, 0, 1, 1, 0, 1])  # 0表示动作片，1表示喜剧片"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. 创建 KNN 模型\n",
    "k = 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "k = 1\n",
    "knn = KNeighborsClassifier(n_neighbors=k)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>#sk-container-id-1 {\n",
       "  /* Definition of color scheme common for light and dark mode */\n",
       "  --sklearn-color-text: black;\n",
       "  --sklearn-color-line: gray;\n",
       "  /* Definition of color scheme for unfitted estimators */\n",
       "  --sklearn-color-unfitted-level-0: #fff5e6;\n",
       "  --sklearn-color-unfitted-level-1: #f6e4d2;\n",
       "  --sklearn-color-unfitted-level-2: #ffe0b3;\n",
       "  --sklearn-color-unfitted-level-3: chocolate;\n",
       "  /* Definition of color scheme for fitted estimators */\n",
       "  --sklearn-color-fitted-level-0: #f0f8ff;\n",
       "  --sklearn-color-fitted-level-1: #d4ebff;\n",
       "  --sklearn-color-fitted-level-2: #b3dbfd;\n",
       "  --sklearn-color-fitted-level-3: cornflowerblue;\n",
       "\n",
       "  /* Specific color for light theme */\n",
       "  --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n",
       "  --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n",
       "  --sklearn-color-icon: #696969;\n",
       "\n",
       "  @media (prefers-color-scheme: dark) {\n",
       "    /* Redefinition of color scheme for dark theme */\n",
       "    --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n",
       "    --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n",
       "    --sklearn-color-icon: #878787;\n",
       "  }\n",
       "}\n",
       "\n",
       "#sk-container-id-1 {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 pre {\n",
       "  padding: 0;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-hidden--visually {\n",
       "  border: 0;\n",
       "  clip: rect(1px 1px 1px 1px);\n",
       "  clip: rect(1px, 1px, 1px, 1px);\n",
       "  height: 1px;\n",
       "  margin: -1px;\n",
       "  overflow: hidden;\n",
       "  padding: 0;\n",
       "  position: absolute;\n",
       "  width: 1px;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-dashed-wrapped {\n",
       "  border: 1px dashed var(--sklearn-color-line);\n",
       "  margin: 0 0.4em 0.5em 0.4em;\n",
       "  box-sizing: border-box;\n",
       "  padding-bottom: 0.4em;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-container {\n",
       "  /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n",
       "     but bootstrap.min.css set `[hidden] { display: none !important; }`\n",
       "     so we also need the `!important` here to be able to override the\n",
       "     default hidden behavior on the sphinx rendered scikit-learn.org.\n",
       "     See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n",
       "  display: inline-block !important;\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-text-repr-fallback {\n",
       "  display: none;\n",
       "}\n",
       "\n",
       "div.sk-parallel-item,\n",
       "div.sk-serial,\n",
       "div.sk-item {\n",
       "  /* draw centered vertical line to link estimators */\n",
       "  background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n",
       "  background-size: 2px 100%;\n",
       "  background-repeat: no-repeat;\n",
       "  background-position: center center;\n",
       "}\n",
       "\n",
       "/* Parallel-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item::after {\n",
       "  content: \"\";\n",
       "  width: 100%;\n",
       "  border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n",
       "  flex-grow: 1;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel {\n",
       "  display: flex;\n",
       "  align-items: stretch;\n",
       "  justify-content: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  position: relative;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:first-child::after {\n",
       "  align-self: flex-end;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:last-child::after {\n",
       "  align-self: flex-start;\n",
       "  width: 50%;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-parallel-item:only-child::after {\n",
       "  width: 0;\n",
       "}\n",
       "\n",
       "/* Serial-specific style estimator block */\n",
       "\n",
       "#sk-container-id-1 div.sk-serial {\n",
       "  display: flex;\n",
       "  flex-direction: column;\n",
       "  align-items: center;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  padding-right: 1em;\n",
       "  padding-left: 1em;\n",
       "}\n",
       "\n",
       "\n",
       "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n",
       "clickable and can be expanded/collapsed.\n",
       "- Pipeline and ColumnTransformer use this feature and define the default style\n",
       "- Estimators will overwrite some part of the style using the `sk-estimator` class\n",
       "*/\n",
       "\n",
       "/* Pipeline and ColumnTransformer style (default) */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable {\n",
       "  /* Default theme specific background. It is overwritten whether we have a\n",
       "  specific estimator or a Pipeline/ColumnTransformer */\n",
       "  background-color: var(--sklearn-color-background);\n",
       "}\n",
       "\n",
       "/* Toggleable label */\n",
       "#sk-container-id-1 label.sk-toggleable__label {\n",
       "  cursor: pointer;\n",
       "  display: block;\n",
       "  width: 100%;\n",
       "  margin-bottom: 0;\n",
       "  padding: 0.5em;\n",
       "  box-sizing: border-box;\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:before {\n",
       "  /* Arrow on the left of the label */\n",
       "  content: \"▸\";\n",
       "  float: left;\n",
       "  margin-right: 0.25em;\n",
       "  color: var(--sklearn-color-icon);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 label.sk-toggleable__label-arrow:hover:before {\n",
       "  color: var(--sklearn-color-text);\n",
       "}\n",
       "\n",
       "/* Toggleable content - dropdown */\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content {\n",
       "  max-height: 0;\n",
       "  max-width: 0;\n",
       "  overflow: hidden;\n",
       "  text-align: left;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content pre {\n",
       "  margin: 0.2em;\n",
       "  border-radius: 0.25em;\n",
       "  color: var(--sklearn-color-text);\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-toggleable__content.fitted pre {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n",
       "  /* Expand drop-down */\n",
       "  max-height: 200px;\n",
       "  max-width: 100%;\n",
       "  overflow: auto;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n",
       "  content: \"▾\";\n",
       "}\n",
       "\n",
       "/* Pipeline/ColumnTransformer-specific style */\n",
       "\n",
       "#sk-container-id-1 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator-specific style */\n",
       "\n",
       "/* Colorize estimator box */\n",
       "#sk-container-id-1 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label label.sk-toggleable__label,\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  /* The background is the default theme color */\n",
       "  color: var(--sklearn-color-text-on-default-background);\n",
       "}\n",
       "\n",
       "/* On hover, darken the color of the background */\n",
       "#sk-container-id-1 div.sk-label:hover label.sk-toggleable__label {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "/* Label box, darken color on hover, fitted */\n",
       "#sk-container-id-1 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n",
       "  color: var(--sklearn-color-text);\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Estimator label */\n",
       "\n",
       "#sk-container-id-1 div.sk-label label {\n",
       "  font-family: monospace;\n",
       "  font-weight: bold;\n",
       "  display: inline-block;\n",
       "  line-height: 1.2em;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-label-container {\n",
       "  text-align: center;\n",
       "}\n",
       "\n",
       "/* Estimator-specific */\n",
       "#sk-container-id-1 div.sk-estimator {\n",
       "  font-family: monospace;\n",
       "  border: 1px dotted var(--sklearn-color-border-box);\n",
       "  border-radius: 0.25em;\n",
       "  box-sizing: border-box;\n",
       "  margin-bottom: 0.5em;\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-0);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-0);\n",
       "}\n",
       "\n",
       "/* on hover */\n",
       "#sk-container-id-1 div.sk-estimator:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-2);\n",
       "}\n",
       "\n",
       "#sk-container-id-1 div.sk-estimator.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-2);\n",
       "}\n",
       "\n",
       "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n",
       "\n",
       "/* Common style for \"i\" and \"?\" */\n",
       "\n",
       ".sk-estimator-doc-link,\n",
       "a:link.sk-estimator-doc-link,\n",
       "a:visited.sk-estimator-doc-link {\n",
       "  float: right;\n",
       "  font-size: smaller;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1em;\n",
       "  height: 1em;\n",
       "  width: 1em;\n",
       "  text-decoration: none !important;\n",
       "  margin-left: 1ex;\n",
       "  /* unfitted */\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted,\n",
       "a:link.sk-estimator-doc-link.fitted,\n",
       "a:visited.sk-estimator-doc-link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n",
       ".sk-estimator-doc-link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover,\n",
       "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n",
       ".sk-estimator-doc-link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "/* Span, style for the box shown on hovering the info icon */\n",
       ".sk-estimator-doc-link span {\n",
       "  display: none;\n",
       "  z-index: 9999;\n",
       "  position: relative;\n",
       "  font-weight: normal;\n",
       "  right: .2ex;\n",
       "  padding: .5ex;\n",
       "  margin: .5ex;\n",
       "  width: min-content;\n",
       "  min-width: 20ex;\n",
       "  max-width: 50ex;\n",
       "  color: var(--sklearn-color-text);\n",
       "  box-shadow: 2pt 2pt 4pt #999;\n",
       "  /* unfitted */\n",
       "  background: var(--sklearn-color-unfitted-level-0);\n",
       "  border: .5pt solid var(--sklearn-color-unfitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link.fitted span {\n",
       "  /* fitted */\n",
       "  background: var(--sklearn-color-fitted-level-0);\n",
       "  border: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "\n",
       ".sk-estimator-doc-link:hover span {\n",
       "  display: block;\n",
       "}\n",
       "\n",
       "/* \"?\"-specific style due to the `<a>` HTML tag */\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link {\n",
       "  float: right;\n",
       "  font-size: 1rem;\n",
       "  line-height: 1em;\n",
       "  font-family: monospace;\n",
       "  background-color: var(--sklearn-color-background);\n",
       "  border-radius: 1rem;\n",
       "  height: 1rem;\n",
       "  width: 1rem;\n",
       "  text-decoration: none;\n",
       "  /* unfitted */\n",
       "  color: var(--sklearn-color-unfitted-level-1);\n",
       "  border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted {\n",
       "  /* fitted */\n",
       "  border: var(--sklearn-color-fitted-level-1) 1pt solid;\n",
       "  color: var(--sklearn-color-fitted-level-1);\n",
       "}\n",
       "\n",
       "/* On hover */\n",
       "#sk-container-id-1 a.estimator_doc_link:hover {\n",
       "  /* unfitted */\n",
       "  background-color: var(--sklearn-color-unfitted-level-3);\n",
       "  color: var(--sklearn-color-background);\n",
       "  text-decoration: none;\n",
       "}\n",
       "\n",
       "#sk-container-id-1 a.estimator_doc_link.fitted:hover {\n",
       "  /* fitted */\n",
       "  background-color: var(--sklearn-color-fitted-level-3);\n",
       "}\n",
       "</style><div id=\"sk-container-id-1\" class=\"sk-top-container\"><div class=\"sk-text-repr-fallback\"><pre>KNeighborsClassifier(n_neighbors=1)</pre><b>In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. <br />On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.</b></div><div class=\"sk-container\" hidden><div class=\"sk-item\"><div class=\"sk-estimator fitted sk-toggleable\"><input class=\"sk-toggleable__control sk-hidden--visually\" id=\"sk-estimator-id-1\" type=\"checkbox\" checked><label for=\"sk-estimator-id-1\" class=\"sk-toggleable__label fitted sk-toggleable__label-arrow fitted\">&nbsp;&nbsp;KNeighborsClassifier<a class=\"sk-estimator-doc-link fitted\" rel=\"noreferrer\" target=\"_blank\" href=\"https://scikit-learn.org/1.5/modules/generated/sklearn.neighbors.KNeighborsClassifier.html\">?<span>Documentation for KNeighborsClassifier</span></a><span class=\"sk-estimator-doc-link fitted\">i<span>Fitted</span></span></label><div class=\"sk-toggleable__content fitted\"><pre>KNeighborsClassifier(n_neighbors=1)</pre></div> </div></div></div></div>"
      ],
      "text/plain": [
       "KNeighborsClassifier(n_neighbors=1)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "knn.fit(X,y)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. 用模型推理(预测)用户的喜好"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "new_user = np.array([[3, 4]])\n",
    "prediction = knn.predict(new_user)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5. 数据可视化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkUAAAHJCAYAAACL5E3/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABgHElEQVR4nO3deVxU9f7H8dewg4BriAuiuWHuuKJ1tQzXm5Jl/tBSU+tWWpqpaXlzq6xrRraZ5VZdycrSNs3Qwj1zo9S8pqbignotBRFFhPP7Yy6TIwMyMMPA+H4+HvPI+Z7v+Z7PZ86Mfjrne84xGYZhICIiInKD83B1ACIiIiKlgYoiEREREVQUiYiIiAAqikREREQAFUUiIiIigIoiEREREUBFkYiIiAigokhEREQEUFEkIiIiAqgoEuHw4cOYTCZMJlOB/YYMGYLJZGLKlCklE5gD5MZsMpn4xz/+kW+/zMxMKlWqZOmbmJhYckH+T26sztx2YmKiJcfcl5eXF6GhofTp04cffvjBadu+WnZ2Ns899xx169bFx8cHk8nEkCFDSmTbIpI/L1cHICIl49NPP+WNN97Ax8cnz7JvvvmGs2fPuiAq16hatSrdu3cH4NKlSyQlJfHll1/y1Vdf8dZbb/Hoo486dfuzZ89m+vTpVK9enb59++Ln58ett97q1G2KyPWpKBK5AbRs2ZKdO3eyYsUKYmJi8iz/97//jaenJ02aNOHnn38u+QCBGTNmMGHCBGrVquX0bUVERLBo0SLLe8MwmDZtGlOmTOGpp57innvuISQkxGnbX758OQDr16/n5ptvdtp2RMQ+On0mcgOIjY3Fw8ODxYsX51l27tw5VqxYQZcuXQgNDXVBdGbVqlUjIiKCgICAEt+2yWTin//8J3Xr1uXixYt89913Tt3esWPHAFQQiZQyKopEiik9PZ0ZM2bQvHlzypcvT2BgIHXr1qVfv36sWrUqT/+MjAxmzJhBy5YtCQwMJDAwkPbt2/P+++/bHN9kMlG7dm0uX77MtGnTiIiIwNfX1+YRn/xUq1aNO+64g6+//prU1FSrZZ988gmZmZncf//9BY5x9OhR/vGPfxAeHo6vry8hISH07duXrVu3WvXbsWMHJpOJdu3a5TvWG2+8gclkYsyYMZa2guYU2fuZFYWHhwfNmzcHzLnCX3OQhgwZwsmTJxk+fDg1a9bEy8uL1157zbLu0aNHGTlyJHXr1sXPz49KlSrx97//nU2bNlltIzfHQ4cOAVjNbTp8+HCR8y3Md6SoY2ZnZ/Pyyy/ToEEDfH19CQsL4+mnnyYzM9PmehcuXODll1+mdevWBAcHU65cOSIiIhgxYgS//fZbnv5btmyhX79+VKtWDR8fH2rWrMnw4cNJTk62Ob6IM+n0mUgxZGdnc+edd7JlyxaqVKlC586d8fPz49ixY6xYsYJy5crRrVs3S//Tp08THR3NL7/8QmhoKJ06dcIwDDZt2sSQIUPYtm0bb7zxRp7t5OTkEBMTw7p16+jUqRPNmjWjcuXKdsU6cOBAVq9ezWeffcbQoUMt7YsXLyYgIIC7777b5pEkgF27dnHHHXdw5swZGjZsSN++fUlOTmbZsmV89dVXxMfH069fPwAiIyOJiIjgp59+4uDBg9StWzfPeLnbuV4hBkX/zIri/PnzAPj6+lq1//e//6VNmzZcuXKFW2+9lUuXLlmOaG3evJlevXpx9uxZGjZsSK9evfjvf//LqlWr+Pbbb1m8eDH9+/cHsMwbWrp0KRcuXGDw4MGWbQQGBhYr34K+I8X5DAcMGMCKFSvo3LkzDRs2ZP369fzrX//i+PHj/Pvf/7bqm5KSQnR0NHv27KFixYp07twZX19ffv/9d9555x3q169PgwYNLP3ffvttHn/8cQDatGnDbbfdxr59+5g/fz5ffvkla9eupVGjRoXceyIOYIjc4A4dOmQAxvV+DoMHDzYAY/LkyZa277//3gCMNm3aGBcvXrTqn5qaamzbts2qrWfPngZgjBo1yrh06ZKl/eTJk0br1q0NwFi5cqXVOrmx1atXzzh27JhdueXG/OGHHxppaWmGv7+/cfvtt1uWHzlyxDCZTEZsbKxhGIbRrVs3AzB++OEHS5+cnByjadOmBmCMHz/eyMnJsSxbunSp4eHhYQQGBhonTpywtE+fPt0AjGnTpuWJ6cCBAwZgRERE2Iz16m0bRtE+s/z88MMPBmB06tQpz7JTp04ZwcHBBmAkJCRY9QeMu+++2+Y+rlatmuHp6Wn8+9//tlq2detWo2LFikZgYKBx+vRpq2Xh4eH5ft+c8R0pzpiNGjUyUlJSLO2///67UaFCBQMwDhw4YLVOly5dDMC47777jPPnz1stO3TokPHzzz9b3m/evNnw9PQ0atSoked3Mm/ePAMw2rVrZ/MzEnEWFUVywytOUfTxxx8bgDF69Ojrbmfnzp2WAio7OzvP8h07dhiA0bt3b6v23Ng+/fTTwiVkI+YPP/zQMAzDuO+++wwPDw/LP5wvvviiARjffPONYRi2i6Lcwq9WrVrG5cuX82yjb9++BmA8//zzlrbff//dZuFjGIYxdepUAzCmT59uM9art13Uzyw/toqiixcvGj/++KPRrl07AzAaNmxoXLlyxaq/r6+vzWIjLi7OAIynnnrK5vZeffVVAzBeffVVq/b8iiJnfEeKO2ZugXi1kSNHGoCxcOFCS9uWLVsMwAgJCTHS0tLyrHOtPn36GIDx1Vdf2Vzeu3dvAzB27Nhx3bFEHEVzikSKoUWLFnh4eLBw4ULee+89/vjjj3z75k7ejYmJwcMj708vd67HTz/9lGeZyWTirrvuKna8999/Pzk5OcTHxwPm01ghISF07do133XWr18PwH333Ye3t3ee5Q888IBVP4A6derQoUMH/vOf/7Bjxw6r/rmnzgYOHHjdeIvzmRVk7dq1lrk8/v7+tG/fni1btlCvXj2WL1+Op6enVf/IyEhq1KiRb3x9+/a1uZ3bbrsNoNDxOeM7Upwxvb29uf322/O0554CS0lJsbStXr0aME/qDwoKsplfrpycHNasWUNAQIDV6eWr2fvZiTiCiiK54V3vpo25DMPI079Bgwb861//IiMjg4cffpiQkBCaN2/OmDFj+OWXX6zWz51I++yzz+a5gWDuKz09nTNnzuTZdkhISJ55LkXRvXt3KleuzOLFi9m5cyd79uyhf//+eHnlP73wxIkTANSuXdvm8tz248ePW7XnFj1Xz1Patm0bv/32Gx06dKBOnTrXjbc4n1lBqlatyuDBgxk8eDDDhg1j/PjxfP755/z6669ERETk6Z/fbQJy4+vYsaPN2Nq0aQNQ6Pic8R0pzpihoaF5CkTAUvRcPdk6d3K6rTlk1zpz5gzp6elkZGRYbl557WvcuHGWviIlRROt5YZ39SXgGRkZ+V4SnpGRAUC5cuWs2p966inuu+8+li9fTkJCAuvXrycuLo7XXnuNuLg4Ro0aBZj/7xjMk20L8w/H1fz8/Ozqnx9vb2/uu+8+5syZwzPPPAMUbrJzQfIrKvv378/o0aNZsmQJM2fOtLolQGGOEkHxPrOCXHufouvJ7/PPje/ee+/N8724dnuF4YzvSHHGtHVkyRFyYwoMDOSee+4psG/jxo2dEoOILSqK5IZXqVIl/P39uXjxIr///jtNmjSx2e/3338HoGbNmnmWhYWF8fjjj/P4449z5coVlixZwoMPPsj48eMZNGgQFStWtKwXExPDU0895byEruP+++9nzpw5fPvttzRo0IC2bdsW2L969eoAHDlyxOby3CMR155eqly5Mt26dePrr78mMTGRTp06sWTJEry9vS1XY11PafnM8lOzZk327dvHhAkTaNWqlUPGA8fmW1KfYVhYGAAHDx68bt8qVarg5+dnOfVc2KO1Is6m02dyw/P09KRjx46A+XEXthw9epSkpCQ8PDwsffPj5eXF/fffT5s2bbh8+TL79+8HIDo6GoBly5Y5MHr7dejQgebNm1O5cmWrS/Pzkzu349NPPyU7OzvP8tzLsnP7XS33iFB8fDzff/89J0+epFu3boW+nUBp+czy4+j4nJFvSX2Gd955JwAfffQR6enpBfb18vKic+fOpKWlsWbNGqfGJWIPFUUiYDnF9dJLL7FlyxarZampqQwdOpScnBz69u1r+T9igB9++IHVq1dbTgfkOnToEHv37sVkMln+T71du3ZER0ezceNGRowYQVpaWp44fv75Z7799ltHp5dHUlISZ86c4emnn75u386dO9O0aVMOHz7Mc889Z5lbBeZ/aD///HMCAwNtFlh9+vQhKCiIzz77jAULFgCFP3UGpeszs+Uf//gHISEh/Otf/+Ldd9/N8z24cuUKq1atYvfu3YUazxn5ltRn2LZtW26//XZOnz7Nww8/zIULF6yWHz58mF27dlneP/vss3h4ePDggw/avGFneno6CxYs4OLFi8WKS8Qurr78TaS0GD9+vAEYHh4eRlRUlDFgwACjV69eRvny5Q3AaNKkSZ77zeRekn3TTTcZ3bt3NwYOHGh07drV8PX1NQDj8ccft+p/6tQpo2XLlgZgVKhQwejcubNlO2FhYZZ7yVwNMMLDw4uU07WX5F+PrUvyDcMwfvnlF6Ny5cqW+9bExsYaHTt2NADDy8vL+Pjjj/Mdc9CgQZbLu4OCgoyMjIwCY71220X5zPJT0H2KCuo/ePDgfPts3rzZqFKligEYYWFhRo8ePYwBAwYYd9xxh+V+PsuWLbNap6D7FDnjO+LoMRcuXJjn9hSGYRjHjh0zGjZs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IiIiIiXB7qKoXLlylnlE1apV4+DBg5ZlZ86ccVxkIiIiIiXI7jlF7du3Z8OGDTRq1IiePXvy1FNPsWvXLj7//HPat2/vjBhFREREnM7uoujVV18lPT0dgKlTp5Kens7HH39M/fr1deWZiIiIlFl2FUXZ2dkcO3aMZs2aAeZTabqLtYiIiLgDu+YUeXp60rVrV86ePeuseERERERcwu6J1k2aNOH33393RiwiIiIiLmN3UfT8888zduxYvv76a1JSUkhLS7N6iYiIiJRFdk+07tmzJwC9e/fGZDJZ2g3DwGQykZ2d7bjoREREREqIHggrIiIiQhGKok6dOjkjDhERERGXsntOkYiIiIg7UlEkIiIigooiEREREcDFRdGcOXNo1qwZwcHBBAcHExUVxcqVKwtc59NPPyUiIgI/Pz+aNm3KihUrSihaERERcWfFLoouX75seRaavWrWrMlLL73E9u3b2bZtG3fccQd9+vRhz549Nvtv2rSJ2NhYhg0bxs6dO4mJiSEmJobdu3cXJwURERER+4qihQsX8vjjj7N48WIAJk6cSFBQEOXLlyc6Opo//vjDro3fdddd9OzZk/r169OgQQNeeOEFAgMD+fHHH232nz17Nt27d2fcuHE0atSI6dOnExkZyZtvvmnXdkVERESuVehL8l944QVeeOEFOnbsSHx8PBs2bGD58uVMmzYNDw8PXn/9dSZNmsScOXOKFEh2djaffvopFy5cICoqymafzZs3M2bMGKu2bt26sXz58nzHzczMJDMz0/I+967bWVlZZGVlFSnW/OSO5+hxSwt3zw/cP0flV/a5e47Kr+xzVo4l8ZmZDMMwCtOxfv36TJs2jdjYWLZt20a7du345JNPuOeeewBYuXIljzzyCEeOHLErgF27dhEVFcWlS5cIDAwkPj7ectfsa/n4+PD+++8TGxtraXv77beZOnUqp06dsrnOlClTmDp1ap72+Ph4AgIC7IpVREREXCMjI4MBAwaQmppKcHCwU7ZR6CNFycnJ3HrrrQC0bt0aLy8vmjRpYlnerFkzUlJS7A6gYcOGJCUlkZqaytKlSxk8eDBr167llltusXssWyZOnGh1dCktLY2wsDC6du3q8A81KyuLhIQEoqOj8fb2dujYpYG75wfun6PyK/vcPUflV/Y5K8eSeL5qoYuirKwsfH19Le99fHyskvXy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e9OyZUsOHDhgc7mvry++vr4213PWF9KZY5cG7p4fuH+Oyq/sc/cclV/Z5+gcS+LzsuuSfF9fX2JjY0lISODXX3+lcePGPPbYY9SuXZv09HS7N24YBiNHjmTZsmV8//331KlTx+4xsrOz2bVrF9WqVbN7XREREZFcRb76zMPDA5PJhGEYZGdnF2mMESNGEB8fzxdffEFQUBAnT54EoHz58vj7+wMwaNAgatSowYwZMwCYNm0a7du3p169epw7d46ZM2dy5MgRhg8fXtRUREREROw7UpSZmclHH31EdHQ0DRo0YNeuXbz55pskJycTGBho98bnzJlDamoqnTt3plq1apbXxx9/bOmTnJxMSkqK5f3Zs2d56KGHaNSoET179iQtLY1NmzZxyy232L19ERERkVyFPlL02GOPsWTJEsLCwhg6dCgfffQRVapUKdbGCzPHOzEx0ep9XFwccXFxxdquiIiIyLUKXRS988471KpVi5tvvpm1a9eydu1am/0+//xzhwUnIiIiUlIKXRQNGjRIj9MQERERt1XoomjRokVODENERETEteyaaC0iIiLirlQUiYiIiKCiSERERARQUSQiIiICqCgSERERAVQUiYiIiAAqikREREQAFUUiIiIigIoiEREREUBFkYiIiAigokhEREQEUFEkIiIiAqgoEhEREQFUFImIm/rjjz8ICQnh8OHDJbrdy5cvU7t2bbZt21ai23VH2odS0lQUiYhbeuGFF+jTpw+1a9cGzP/Adu/enerVq+Pr60tYWBgjR44kLS3NrnFnzJhBmzZtCAoKIiQkhJiYGPbt22dZ7uPjw9ixY3n66acdmc4N6dp9eLU//viDmjVrYjKZOHfunF3jah9KflQUiYjbycjIYP78+QwbNszS5uHhQZ8+ffjyyy/57bffWLRoEatXr+aRRx6xa+y1a9cyYsQIfvzxRxISEsjKyqJr165cuHDB0mfgwIFs2LCBPXv2OCynG42tfXi1YcOG0axZsyKNrX0o+VFRJCJuZ+XKlfj6+tK+fXtLW8WKFXn00Udp3bo14eHhdOnShccee4z169fbNfa3337LkCFDaNy4Mc2bN2fRokUkJyezfft2q2117NiRJUuWOCynG42tfZhrzpw5nDt3jrFjxxZpbO1DyY+XqwMQEXG0jRs30qpVqwL7nDhxgs8//5xOnToVa1upqakA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xMQ8bf369aNfv35OiEhERERuVHr2mYiIiAgqikREREQAFUUiIiIigIoiEREREUBFkYiIiAigokhEREQEUFEkIiIiAqgoEhEREQFUFImIiIgAKopEREREABVFIiIiIoCKIhERERFARZGIiIgIoKJIREREBFBRJCIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERARQUSQiIiICqCgSERERAVQUiYiIiAAqikREREQAFUUiIiIigIoiEREREUBFkYiIiAigokhEREQEUFEkIiIiAri4KFq3bh133XUX1atXx2QysXz58gL7JyYmYjKZ8rxOnjxZMgGLiIiI23JpUXThwgWaN2/OW2+9Zdd6+/btIyUlxfIKCQlxUoQiIiJyo/By5cZ79OhBjx497F4vJCSEChUqOD4gERERuWG5tCgqqhYtWpCZmUmTJk2YMmUKHTt2zLdvZmYmmZmZlvdpaWkAZGVlkZWV5dC4csdz9LilhbvnB+6fo/Ir+9w9R+VX9jkrx5L4zEyGYRhO30ohmEwmli1bRkxMTL599u3bR2JiIq1btyYzM5N58+bx4YcfsmXLFiIjI22uM2XKFKZOnZqnPT4+noCAAEeFLyIiIk6UkZHBgAEDSE1NJTg42CnbKFNFkS2dOnWiVq1afPjhhzaX2zpSFBYWxpkzZxz+oWZlZZGQkEB0dDTe3t4OHbs0cPf8wP1zVH5ln7vnqPzKPmflmJaWRpUqVZxaFJXJ02dXa9u2LRs2bMh3ua+vL76+vnnavb29nfaFdObYpYG75wfun6PyK/vcPUflV/Y5OseS+LzK/H2KkpKSqFatmqvDEBERkTLOpUeK0tPTOXDggOX9oUOHSEpKolKlStSqVYuJEydy/PhxPvjgAwBee+016tSpQ+PGjbl06RLz5s3j+++/57vvvnNVCiIiIuImXFoUbdu2jdtvv93yfsyYMQAMHjyYRYsWkZKSQnJysmX55cuXeeqppzh+/DgBAQE0a9aM1atXW40hIiIiUhQuLYo6d+5MQfO8Fy1aZPV+/PjxjB8/3slRiYiIyI2ozM8pEhEREXEEFUUiIiIiqCgSERERAVQUiYiIiAAqikREREQAFUUiIiIigIoiEREREUBFkYiIiAigokhEREQEUFEkIiIiAqgoEhEREQFUFImIiIgA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3nsvTZo0sXoNGzaMM2fO8O2339qVd/369fnwww/Zu3cvW7ZsYeDAgfj7+1v1qV27NmvWrOHkyZNFLmIiIiK48847efjhh/npp5/YuXMnDz/8sM2jVyJSMlQUiUi+goODCQ4Oznf5Sy+9xD333MMDDzxAZGQkBw4cYNWqVXnmxQwcOJCff/6Zu+++O0+BcbWAgADWrVtHrVq16Nu3L40aNWLYsGFcunTJZhzbt2/n559/5p577smzrHz58nTp0oX58+fbkbG5yDp79iyRkZE88MADllsOXG3WrFkkJCQQFhaW5zYF9vjggw+oWrUqf/vb37j77rt56KGHCAoKws/Pr8hjikjRmQzDMFwdhIiIwLFjxwgLC2P16tV06dLF1eGI3HBUFImIuMj3339Peno6TZs2JSUlhfHjx3P8+HF+++23PJO0RcT5dPWZiIiLZGVl8cwzz/D7778TFBREhw4dWLx4sQoiERfRkSIRERERNNFaREREBFBRJCIiIgKoKBIREREBVBSJiIiIACqKRERERAAVRSIiIiKAiiIRERERQEWRiIiICKCiSERERASA/wepAsffuJZqIwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.title(\"User Movie Preference\", size=15) \n",
    "plt.xlabel(\"Movie A rating\")\n",
    "plt.ylabel(\"Movie B rating\")\n",
    "plt.grid()\n",
    "\n",
    "# 绘制原始样本点，要求不同的影片喜好类别用不同的颜色标记\n",
    "# 提示: 用scatter散点图绘制，用它的参数c实现不同的类别用不同的颜色标记\n",
    "plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.bwr, marker='o')#TODO\n",
    "\n",
    "# 绘制新数据点，用红色x标记，大小为8\n",
    "# 提示：用plt.plot()绘制，用它的参数marker实现不同的标记符号\n",
    "plt.plot(new_user[0, 0], new_user[0, 1], 'rx', markersize=8)#TODO\n",
    "\n",
    "# 新数据最近邻索引为第一个最近邻的索引\n",
    "dist, idx = knn.kneighbors(new_user)#TODO\n",
    "nearest = X[idx[0][0]]#TODO # 获取最近邻点的坐标，这是一个列表，第一个元素是x坐标，第二个元素是y坐标\n",
    "\n",
    "# 用红线标记新数据点与最近邻点的连接线\n",
    "# 提示：用plt.plot()绘制，用 r-- 实现红色虚线\n",
    "plt.plot([new_user[0, 0], nearest[0]], [new_user[0, 1], nearest[1]], 'r--')#TODO\n",
    "\n",
    "# 为每个点添加坐标文本  \n",
    "for x, y in zip(X[:, 0], X[:, 1]):\n",
    "    plt.text(x, y+0.1, f'({x}, {y})') \n",
    "\n",
    "# 为新数据点添加坐标文本\n",
    "plt.text(new_user[0,0], new_user[0,1]+0.1, f'({new_user[0,0]}, {new_user[0,1]})')\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
